package com.share.domain.strategy.service.Raffle;

import com.share.domain.strategy.model.entity.StrategyAwardEntity;
import com.share.domain.strategy.model.vo.RuleTreeVo;
import com.share.domain.strategy.model.vo.RuleWeightVo;
import com.share.domain.strategy.model.vo.StrategyAwardRuleModelVo;
import com.share.domain.strategy.model.vo.StrategyAwardStockKeyVo;
import com.share.domain.strategy.repository.IStrategyRepository;
import com.share.domain.strategy.service.AbstractRaffleStrategy;
import com.share.domain.strategy.service.IRaffleAward;
import com.share.domain.strategy.service.IRaffleRule;
import com.share.domain.strategy.service.IRaffleStock;
import com.share.domain.strategy.service.armory.IStrategyDispatch;
import com.share.domain.strategy.service.rule.chain.ILogicChain;
import com.share.domain.strategy.service.rule.chain.factory.DefaultChainFactory;
import com.share.domain.strategy.service.rule.tree.factory.DefaultTreeFactory;
import com.share.domain.strategy.service.rule.tree.factory.engine.IDecisionTreeEngine;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class DefaultRaffleStrategy extends AbstractRaffleStrategy implements IRaffleAward, IRaffleStock, IRaffleRule {
    public DefaultRaffleStrategy(IStrategyRepository repository, IStrategyDispatch strategyDispatch, DefaultChainFactory defaultChainFactory, DefaultTreeFactory defaultTreeFactory) {
        super(repository, strategyDispatch, defaultChainFactory, defaultTreeFactory);
    }


    @Override
    public DefaultChainFactory.StrategyAwardVo raffleLogicChain(String userId, Long strategyId) {
        ILogicChain logicChain = defaultChainFactory.openLogicChain(userId, strategyId);
        return logicChain.logic(userId,strategyId);
    }

    @Override
    public DefaultTreeFactory.StrategyAwardVo raffleLogicTree(String userId, Long strategyId, Integer awardId) {
        return raffleLogicTree(userId,strategyId,awardId,null);
    }

    @Override
    protected DefaultTreeFactory.StrategyAwardVo raffleLogicTree(String userId, Long strategyId, Integer awardId, Date endDateTime) {
        StrategyAwardRuleModelVo strategyAwardRuleModelVo = repository.queryStrategyAwardRuleModelVo(strategyId,awardId);
        if(null == strategyAwardRuleModelVo)
        {
            return DefaultTreeFactory.StrategyAwardVo.builder()
                    .awardId(awardId).build();
        }
        RuleTreeVo ruleTreeVo = repository.queryRuleTreeVoByTreeId(strategyAwardRuleModelVo.getRuleModels());
        if(null==ruleTreeVo){
            throw new RuntimeException("存在抽奖策略配置的规则模型Key,未在库表rule_tree rule_tree_node rule_tree_line配置对应规则树信息");
        }
        IDecisionTreeEngine treeengine = defaultTreeFactory.openLogicTree(ruleTreeVo);
        return treeengine.process(userId,strategyId,awardId,endDateTime);
    }


    @Override
    public StrategyAwardStockKeyVo takeQueueValue() throws InterruptedException {
        return repository.takeQueueValue();
    }

    @Override
    public void updateStrategyAwardStock(Long strategyId, Integer awardId) {
        repository.updateStrategyAwardStock(strategyId,awardId);
    }

    @Override
    public List<StrategyAwardEntity> queryRaffleStrategyAwardList(Long strategyId) {
        return repository.queryStrategyAwardList(strategyId);
    }

    @Override
    public List<StrategyAwardEntity> queryRaffleStrategyAwardListByActivityId(Long activityId) {
        Long strategyId = repository.queryStrategyIdByActivityId(activityId);
        return queryRaffleStrategyAwardList(strategyId);
    }

    @Override
    public Map<String, Integer> queryAwardRuleLockCount(String[] treeIds) {
        return repository.queryAwardRuleLockCount(treeIds);
    }

    @Override
    public List<RuleWeightVo> queryRuleWeight(Long strategyId) {
        return repository.queryRuleWeight(strategyId);
    }

    @Override
    public List<RuleWeightVo> queryRuleWeightByActivityId(Long activityId) {
        Long strategyId = repository.queryStrategyIdByActivityId(activityId);
        return queryRuleWeight(strategyId);
    }
}
